/*=============================================================================
*
*   Copyright (C) 2020 All rights reserved.
*
*   Filename:		iterator.hpp
*
*   Author: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Date: 2020-01-17 16:53
*
*   Last Editors: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Last modified:	2020-03-27 23:20
*
*   Description:
*
=============================================================================*/
/// entity iterator learned from dolfin https://github.com/FEniCS/dolfin
/// salute to good design.

#if !defined(ENTITY_ITERATOR_CLASS_H)
#define ENTITY_ITERATOR_CLASS_H

namespace geoxfem {
namespace util {

template <typename T>
struct Range {
  Range(T begin, T end) : __begin(begin), __end(end) {}
  T begin() {
    return __begin;
  }
  T end() {
    return __end;
  }

private:
  T __begin;
  T __end;
};

}  // namespace util
}  // namespace geoxfem

#define nodesIn(obj) \
  geoxfem::util::Range((obj).getNodeBegin(), (obj).getNodeEnd())
#define shapesIn(obj, dim) \
  geoxfem::util::Range((obj).getShapeBegin(dim), (obj).getShapeEnd(dim))
#define cellsIn(obj) \
  shapesIn((obj), geoxfem::traits::get_topology_dimension::apply(obj))
/* #define cellsIn(obj) shapesIn((obj), (obj).getDimension()) */
#define neighborsIn(obj, dim) \
  geoxfem::util::Range((obj).getNeighbourBegin(dim), (obj).getNeighbourEnd(dim))
#define gpsIn(obj) \
  geoxfem::util::Range((obj).getGaussPointBegin(), (obj).getGaussPointEnd())
#define dofsIn(obj) geoxfem::util::Range((obj).getDofBegin(), (obj).getDofEnd())
#define pointsIn(obj) \
  geoxfem::util::Range((obj).getPointBegin(), (obj).getPointEnd())
#define BCNodesIn(obj) \
  geoxfem::util::Range((obj).getBCNodeBegin(), (obj).getBCNodeEnd())

#define childrenIn(obj) \
  geoxfem::util::Range((obj).getChildBegin(), (obj).getChildEnd())

#define cracksIn(obj) \
  geoxfem::util::Range((obj).getCrackBegin(), (obj).getCrackEnd())

#define verticesIn(obj) neighborsIn((obj), 0)
#define segmentsIn(obj) neighborsIn((obj), 1)
#define planesIn(obj) neighborsIn((obj), 2)
#define volumeIn(obj) neighborsIn((obj), 3)

#define facetsIn(obj) neighborsIn((obj), (obj).getDimension() - 1)

#endif  // _ENTITY_ITERATOR_CLASS_H
